package com.sq.util;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamUtil {

    @SuppressWarnings("unchecked")
    public static <T> Stream<T> stream(Collection<T> list) {
        if (list == null) {
            return ((List<T>) Collections.emptyList()).stream();
        }
        return list.stream();
    }

    public static <T> long sum(Collection<T> list, ToLongFunction<? super T> mapper) {
        if (list == null || list.isEmpty()) {
            return 0;
        }
        return list.stream().mapToLong(mapper).sum();
    }

    public static <T, K> List<K> toList(Collection<T> list, Function<? super T, ? extends K> mapper) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyList();
        }
        return list.stream().map(mapper).collect(Collectors.toList());
    }

    public static <T, K> Set<K> toSet(Collection<T> list, Function<? super T, ? extends K> mapper) {
        if (list == null || list.isEmpty()) {
            return Collections.emptySet();
        }
        return list.stream().map(mapper).collect(Collectors.toSet());
    }

    public static <T> void forEach(Collection<T> list, Consumer<? super T> action) {
        if (list == null || list.isEmpty()) {
            return;
        }
        list.forEach(action);
    }

    public static <T, K, V> Map<K, V> toMap(Collection<T> list, Function<? super T, ? extends K> keyMapper,
            Function<? super T, ? extends V> valueMapper) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, valueMapper, (oldValue, newValue) -> newValue));
    }

    public static <K, T> Map<K, List<T>> groupingBy(Collection<T> list, Function<? super T, ? extends K> classifier) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.groupingBy(classifier));
    }

    public static <K, T> Map<K, Integer> groupingSumInt(Collection<T> list, Function<? super T, ? extends K> classifier,
            ToIntFunction<? super T> mapper) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.groupingBy(classifier, Collectors.summingInt(mapper)));
    }

    public static <K, T> Map<K, Long> groupingSumLong(Collection<T> list, Function<? super T, ? extends K> classifier,
            ToLongFunction<? super T> mapper) {
        if (list == null || list.isEmpty()) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.groupingBy(classifier, Collectors.summingLong(mapper)));
    }
}
